package io.renren.modules.app.service.impl;
import java.math.BigDecimal;
import java.sql.Timestamp;
import java.time.LocalDateTime;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alipay.api.domain.AlipayTradeAppPayModel;
import com.alipay.api.response.AlipayTradeRefundResponse;
import com.github.wxpay.sdk.WXPayConstants;
import com.github.wxpay.sdk.WXPayUtil;
import io.renren.common.aliPay.AliConfig;
import io.renren.common.aliPay.AliPayHelper;
import io.renren.common.enums.ErrorCode;
import io.renren.common.exception.RRException;
import io.renren.common.utils.IPUtils;
import io.renren.common.utils.SnowflakeIdWorker;
import io.renren.common.wxPay.WxConfig;
import io.renren.common.wxPay.WxPayHelper;
import io.renren.common.wxPay.WxPayReqDto;
import io.renren.modules.app.dto.CreateOrderRespDto;
import io.renren.modules.app.req.BalanceRechargeReq;
import io.renren.modules.app.utils.AuthUtils;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.renren.common.utils.PageUtils;
import io.renren.common.utils.Query;

import io.renren.modules.app.dao.BalanceOrderDao;
import io.renren.modules.app.entity.BalanceOrderEntity;
import io.renren.modules.app.service.BalanceOrderService;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


@Service("balanceOrderService")
public class BalanceOrderServiceImpl extends ServiceImpl<BalanceOrderDao, BalanceOrderEntity> implements BalanceOrderService {

    @Resource
    protected HttpServletRequest httpServletRequest;

    @Resource
    protected WxPayHelper wxPayHelper;

    @Resource
    protected WxConfig wxConfig;

    @Resource
    protected AliPayHelper aliPayHelper;

    @Resource
    protected AliConfig aliConfig;
    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<BalanceOrderEntity> page = this.page(
                new Query<BalanceOrderEntity>().getPage(params),
                new QueryWrapper<BalanceOrderEntity>()
        );

        return new PageUtils(page);
    }

    /**
     *用户个人余额充值
     * @param balanceRechargeReq
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRED,rollbackFor = Exception.class)
    public CreateOrderRespDto balanceRecharge(BalanceRechargeReq balanceRechargeReq) {
        CreateOrderRespDto respDto = new CreateOrderRespDto();
        if(balanceRechargeReq.getMoney().compareTo(BigDecimal.valueOf(0)) == -1){
            throw new RRException(ErrorCode.PARAM_ERROR.getMessage(),ErrorCode.PARAM_ERROR.getCode());
        }
        BalanceOrderEntity balanceOrder = new BalanceOrderEntity();
        balanceOrder.setMoney(balanceRechargeReq.getMoney());
        balanceOrder.setOrderNumber(SnowflakeIdWorker.getNextOrderNo("YEDD"));
        balanceOrder.setPayType(balanceRechargeReq.getPayType());
        balanceOrder.setUserId(AuthUtils.getUserId());
        switch (balanceRechargeReq.getPayType()) {
            case 1:
                WxPayReqDto reqDto = new WxPayReqDto();
                reqDto.setBody(String.format("%s订单:%s", "人人余额充值",balanceOrder.getOrderNumber()));
                reqDto.setSpbill_create_ip(IPUtils.getIpAddr(httpServletRequest));
                reqDto.setOut_trade_no(balanceOrder.getOrderNumber());
                reqDto.setTotal_fee(String.valueOf(balanceRechargeReq.getMoney().multiply(BigDecimal.valueOf(100)).intValue()));
                final Map<String, String> pay = wxPayHelper.pay(reqDto);
                JSONObject payMap = new JSONObject();
                String sign = "";
                try {
//                    payMap.put("package", String.format("prepay_id=%s", pay.get("prepay_id")));
                    //封装微信app支付参数
                    payMap.put("package", "Sign=WXPay");
                    payMap.put("partnerid", wxConfig.getMchID());
                    payMap.put("prepayid", pay.get("prepay_id"));
                    payMap.put("noncestr", pay.get("nonce_str"));
                    payMap.put("appid", pay.get("appid"));
//                    payMap.put("signtype", "MD5");
//                    redisRepository.set(super.getPayCacheKey(order.getOrderCode()), payMap.toJSONString(), 1800L, TimeUnit.SECONDS);
                    payMap.put("timestamp", String.valueOf(Timestamp.valueOf(LocalDateTime.now()).getTime() / 1000));
                    sign = WXPayUtil.generateSignature((Map) payMap, wxConfig.getKey());
                } catch (Exception e) {
                    throw new RRException("请求微信支付失败",2001);
                }
                payMap.put("sign", sign);
                respDto.setPayHub(payMap);
                break;
            case 2:
                try {
                    JSONObject payHub = new JSONObject();
                    AlipayTradeAppPayModel model = new AlipayTradeAppPayModel();
                    model.setBody(String.format("%s订单:%s", "人人余额充值",balanceOrder.getOrderNumber()));
                    model.setSubject(String.format("%s订单:%s", "人人余额充值",balanceOrder.getOrderNumber()));
                    model.setOutTradeNo(balanceOrder.getOrderNumber());
                    model.setTimeoutExpress("30m");
                    model.setTotalAmount(String.valueOf(balanceRechargeReq.getMoney().doubleValue()));
                    final String pay1 = aliPayHelper.pay(model);
                    payHub.put("appid", aliConfig.getAppId());
                    payHub.put("alipay", pay1);
//                    redisRepository.set(super.getPayCacheKey(order.getOrderCode()), payHub.toJSONString(), 1800L, TimeUnit.SECONDS);
                    respDto.setPayHub(payHub);
                } catch (Exception e) {
                    throw new RRException("请求支付宝支付失败",2001);
                }
                break;
            default:
                throw new RRException(ErrorCode.PARAM_ERROR.getMessage(),ErrorCode.PARAM_ERROR.getCode());
        }
        return respDto;
    }
    /**
     * @author
     * @description 退款处理
     * @date 2021-01-26 11:54
     **/
    @Override
    public void refundCheck() {
//        final List<TOrder> orders = orderRepository.findAllByStatus(7);
//        for (TOrder order : orders) {
//            try {
//                switch (order.getPayType()) {
//                    case 1:
//                        final Map<String, String> wxRefund = wxPayHelper.refund(order.getOrderCode(), order.getFee(), order.getFee());
//                        order.setRefundNo(wxRefund.get("out_refund_no"));
//                        order.setStatus(8);
//                        break;
//                    case 2:
//                        final AlipayTradeRefundResponse aliRefund = aliPayHelper.refund(order.getOrderCode(), order.getFee());
////                    order.setRefundNo(aliRefund.get());
//                        order.setStatus(8);
//                        break;
//                    case 4:
//                        //返还会员卡次数
//                        String memberCardId = order.getMemberCardId();
//                        TUserCardInner cardInner = userCardInnerRepository.findDistinctFirstByCard(memberCardRepository.findDistinctFirstByCardId(memberCardId));
//                        //如果会员卡刚好过期？ 就先不退次数了
//                        cardInner.setCardUseSum(cardInner.getCardUseSum() - order.getAmount());
//                        cardInner.setCardSum(cardInner.getCardSum() + order.getAmount());
//                        userCardInnerRepository.save(cardInner);
//                        order.setStatus(8);
//                        break;
//                    case 5:
//                        //返还免费次数
//                        order.getUser().setIsFree(Boolean.TRUE);
//                        order.setStatus(8);
//                        break;
//                    default:
//                        break;
//                }
//                super.reverseUseRoom(order.getRoomType().getId(), order.getStartTime().toLocalDateTime(), order.getEndTime().toLocalDateTime(), order.getAmount());
//            } catch (Exception e) {
//                e.printStackTrace();
//                continue;
//            }
//        }
//
//        orderRepository.saveAll(orders);

    }

    /**
     * @author Lee
     * @description 微信回调接口
     * @date 2020-02-23 17:06
     **/
    public String notifyPay(HttpServletRequest request, HttpServletResponse response) {
        String inputLine;
        String notityXml = "";
        String result = "";
        try {
            while ((inputLine = request.getReader().readLine()) != null) {
                notityXml += inputLine;
            }
            request.getReader().close();
            final Map<String, String> resMap = wxPayHelper.checkSign(notityXml);
//            log.debug("微信回调数据:{}", JSON.toJSONString(resMap));
            String orderCode = resMap.get("out_trade_no");
            String tradeNo = resMap.get("transaction_id");
            String timeEnd = resMap.get("time_end");
            String totalFee = resMap.get("total_fee");
//            Order order = orderRepository.findAllByOrderCode(orderCode);
//            Assert.notNull(order, "未查询到订单");
//            if (!order.getTotal().equals(Integer.valueOf(totalFee))) {
//                throw new TrException(666, "金额不相同");
//            }
//            super.orderPaidHandler(order);
//            order.setTradeNo(tradeNo);
//            order.setPayTime(Timestamp.valueOf(LocalDateTime.parse(timeEnd, DateTimeFormatter.ofPattern("yyyyMMddHHmmss"))));
//            orderRepository.save(order);
            result = respXml(WXPayConstants.SUCCESS, "OK");
        } catch (Exception e) {
            e.printStackTrace();
            result = respXml("fail", "xml获取失败");
        }
        if (StringUtils.isEmpty(notityXml)) {
            result = respXml("fail", "xml为空");
        }
//        log.debug(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>微信回调返回结果:{}<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<", result);
        return result;
    }

    /**
     * @author Lee
     * @description 微服务器响应
     * @date 2020-02-23 17:08
     **/
    public String respXml(String return_code, String return_msg) {
        SortedMap<String, String> parameters = new TreeMap<String, String>();
        parameters.put("return_code", return_code);
        parameters.put("return_msg", return_msg);
        return "<xml><return_code><![CDATA[" + return_code + "]]>" +
                "</return_code><return_msg><![CDATA[" + return_msg + "]]></return_msg></xml>";
    }
}